#!/usr/bin/env node
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const fs = require('fs');
const checker = require('license-checker');

const LICENSES_FILE = '../licenses.yaml';
const START_MARKER_LINE = '# Web console modules start';
const END_MARKER_LINE = '# Web console modules end';
const SEPARATOR = '\n\n---\n\n';

const extraLinesForLib = {
  tslib: `notice: |
  /*! *****************************************************************************
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  this file except in compliance with the License. You may obtain a copy of the
  License at http://www.apache.org/licenses/LICENSE-2.0
  THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  MERCHANTABLITY OR NON-INFRINGEMENT.
  See the Apache Version 2.0 License for specific language governing permissions
  and limitations under the License.
  ***************************************************************************** */`
}

function injectConsoleLicenses(consoleLicenses) {
  const text = fs.readFileSync(LICENSES_FILE, 'utf-8');
  const textLines = text.split('\n');

  // Extract the license for the file itself
  let beforeLines = [];
  let afterLines = [];
  let state = 'before';
  for (let textLine of textLines) {
    switch (state) {
      case 'before':
        beforeLines.push(textLine);
        if (textLine === START_MARKER_LINE) {
          state = 'main';
        }
        break;

      case 'main':
        if (textLine === END_MARKER_LINE) {
          state = 'after';
          afterLines.push(textLine);
        }
        break;

      case 'after':
        afterLines.push(textLine);
        break;
    }
  }
  if (state === 'before') throw new Error(`missing starter marker '${START_MARKER_LINE}'`);
  if (state === 'main') throw new Error(`missing ending marker '${END_MARKER_LINE}'`);

  // Write out the new file
  fs.writeFileSync(
    LICENSES_FILE,
    [beforeLines.join('\n'), consoleLicenses.join(SEPARATOR), afterLines.join('\n')].join('\n'),
  );
}

checker.init(
  {
    start: '.',
    production: true,
  },
  function(err, packages) {
    if (err) {
      console.log('err', err);
      return;
    }

    const seen = {};
    const mapped = Object.keys(packages)
      .sort()
      .map(p => {
        const m = p.match(/^(.+)@(\d+\.\d+\.\d+.*)$/);
        if (!m) throw new Error(`Malformed name@version`);
        const name = m[1];
        if (name === 'web-console') return; // This is me!
        if (seen[name]) return; // Dedupe
        seen[name] = true;

        const version = m[2];
        const meta = packages[p];
        let { publisher, licenses, licenseFile } = meta;
        if (!licenses) throw new Error(`Package '${p} does not have a licenses`);

        let properLicenseName; // Map the licenses to their proper name
        let licenseExt; // Map the licenses to the right extension
        switch (licenses) {
          case 'MIT':
            properLicenseName = 'MIT License';
            licenseExt = 'MIT';
            break;

          case 'Apache-2.0':
            properLicenseName = 'Apache License version 2.0';
            licenseExt = 'A2';
            break;

          case 'BSD-3-Clause':
            properLicenseName = 'BSD-3-Clause License';
            licenseExt = 'BSD3';
            break;

          default:
            throw new Error(`Unknown license '${licenses}' in ${p}`);
        }

        const simpleName = name.replace('/', '-');
        const licenseDest = `licenses/bin/${simpleName}.${licenseExt}`;

        let hasLicense = false;
        if (licenseExt !== 'A2') {
          if (licenseFile && licenseFile.match(/\/license(?:\.\w+)?/i)) {
            // If the file ends with license.ext? then copy it over
            try {
              fs.copyFileSync(licenseFile, `../${licenseDest}`);
              hasLicense = true;
            } catch (e) {
              console.log(`Could not copy license for '${p}': ${JSON.stringify(meta)}`);
            }
          } else {
            // See if the license is already there (manually) keep it
            try {
              fs.statSync(`../${licenseDest}`);
              hasLicense = true;
            } catch (e) {
              console.log(`Could not find license for '${p}': ${JSON.stringify(meta)}`);
            }
          }
        }

        if (!publisher && hasLicense) {
          // Extract copyright from license
          const licenseText = fs.readFileSync(`../${licenseDest}`, 'utf-8');
          const m = licenseText.match(
            /(?:^|\n)\s*Copyright(?: (?:\(c\)|©))?(?: 2[0-9]{3}(?:-\w+)?,?)? ([^0-9][^\n]*)\n/m,
          );
          if (m) {
            publisher = m[1]
              .replace(/All rights reserved./i, '')
              .replace(/[0-9-]{4,9}/, '')
              .trim();
          }
        }

        if (!publisher) {
          // Hand coded copyrights
          if (name === 'asap') publisher = 'Contributors';
          if (name === 'diff-match-patch') publisher = 'Google';
        }

        if (!publisher) {
          console.log(`No license for '${name}' ('${licenseDest}')`);
        }

        // Make our blob
        const lines = [
          `name: "${name}"`,
          `license_category: binary`,
          `module: web-console`,
          `license_name: ${properLicenseName}`,
          publisher ? `copyright: ${publisher}` : undefined,
          `version: ${version}`,
          hasLicense ? `license_file_path: ${licenseDest}` : undefined,
          extraLinesForLib[name],
        ];

        return lines.filter(Boolean).join('\n');
      })
      .filter(Boolean);

    injectConsoleLicenses(mapped);
  },
);
